﻿using LuckyShell.FileSys;
using LuckyShell.ShellOrders;
using LuckyShell.ShellValues;

namespace LuckyShell.Commands;

public class FileCommand(List<ShellValue> values) : Command(values)
{
    public override object Run(ref VariateManager manager)
    {
        if (Values.Count <= 1)
            return new VoidValue();
        var v = Values[0].GetValue(ref manager);
        if (v is not string s) throw new Exception("Value is not String");

        if (File.Exists(s))
        {
            var f = new FileInfo(s);
            if (Values.Count == 1)
                manager.Order(s);
            var operaFileObj = Values[1].GetValue(ref manager);
            if (operaFileObj is not string operaFile) throw new Exception("Operation Word is not String");
            switch (operaFile)
            {
                case "Delete" or "delete":
                    f.Delete();
                    break;
                case "Info" or "info":
                    Console.WriteLine(Api.ShowFile(f));
                    break;
                case "Copy" or "copy":
                    if (Values.Count != 3) throw new Exception("Not Enough Parameters");
                    var copyToPathObj = Values[2].GetValue(ref manager);
                    if (copyToPathObj is not string copyToPath) throw new Exception("CopyToPath is not String");
                    f.CopyTo(Path.Combine(copyToPath, f.Name));
                    break;
                case "Move" or "move":
                    if (Values.Count != 3) throw new Exception("Not Enough Parameters");
                    var movePathObj = Values[2].GetValue(ref manager);
                    if (movePathObj is not string movePath) throw new Exception("CopyToPath is not String");
                    f.MoveTo(Path.Combine(movePath, f.Name));
                    break;
                case "Rename" or "rename":
                    if (Values.Count != 3) throw new Exception("Not Enough Parameters");
                    var renamePathObj = Values[2].GetValue(ref manager);
                    if (renamePathObj is not string renamePath) throw new Exception("CopyToPath is not String");
                    f.MoveTo(Path.Combine(f.DirectoryName!, $"{renamePath}{f.Extension}"));
                    break;
            }

            return new VoidValue();
        }

        if (!Directory.Exists(s)) throw new Exception("The Path is not FilePath");
        var d = new DirectoryInfo(s);
        if (Values.Count == 1)
        {
            foreach (var info in d.GetFileSystemInfos())
                Console.WriteLine(info.Name);
            return new VoidValue();
        }

        var operaDirectoryObj = Values[1].GetValue(ref manager);
        if (operaDirectoryObj is not string operaDirectory) throw new Exception("Operation Word is not String");
        switch (operaDirectory)
        {
            case "Delete" or "delete":
                d.Delete();
                break;
            case "Info" or "info":
                Console.WriteLine(Api.ShowDir(d));
                break;
            case "Copy" or "copy":
                if (Values.Count != 3) throw new Exception("Not Enough Parameters");
                var copyToPathObj = Values[2].GetValue(ref manager);
                if (copyToPathObj is not string copyToPath) throw new Exception("CopyToPath is not String");
                var dirInfo = new DirectoryInformation(s);
                dirInfo.Copy(copyToPath);
                break;
            case "Move" or "move":
                if (Values.Count != 3) throw new Exception("Not Enough Parameters");
                var movePathObj = Values[2].GetValue(ref manager);
                if (movePathObj is not string movePath) throw new Exception("CopyToPath is not String");
                d.MoveTo(Path.Combine(movePath, d.Name));
                break;
            case "Rename" or "rename":
                if (Values.Count != 3) throw new Exception("Not Enough Parameters");
                var renamePathObj = Values[2].GetValue(ref manager);
                if (renamePathObj is not string renamePath) throw new Exception("CopyToPath is not String");
                d.MoveTo(Path.Combine(d.Parent?.Name ?? throw new Exception("Not Have Parent Directory"),
                    $"{renamePath}"));
                break;
        }

        return new VoidValue();
    }
}